package com.authine.cloudpivot.web.api.service.impl;

import com.alibaba.dubbo.config.annotation.Reference;
import com.authine.cloudpivot.engine.api.facade.IMMessageFacade;
import com.authine.cloudpivot.engine.api.facade.TaskReportFacade;
import com.authine.cloudpivot.engine.api.model.bizmodel.BizSchemaModel;
import com.authine.cloudpivot.engine.api.model.im.MessageModel;
import com.authine.cloudpivot.engine.api.model.runtime.BizObjectModel;
import com.authine.cloudpivot.engine.api.model.runtime.BizObjectQueryModel;
import com.authine.cloudpivot.engine.api.model.runtime.SelectionValue;
import com.authine.cloudpivot.engine.component.query.api.FilterExpression;
import com.authine.cloudpivot.engine.component.query.api.Page;
import com.authine.cloudpivot.engine.component.query.api.helper.PageableImpl;
import com.authine.cloudpivot.engine.component.query.api.helper.Q;
import com.authine.cloudpivot.engine.enums.type.IMMessageChannelType;
import com.authine.cloudpivot.engine.enums.type.IMMessageType;
import com.authine.cloudpivot.engine.enums.type.QueryDisplayType;
import com.authine.cloudpivot.web.api.dao.ProjectDetailMapper;
import com.authine.cloudpivot.web.api.dao.ResourcesDistributionMapper;
import com.authine.cloudpivot.web.api.dao.TaskOnceMapper;
import com.authine.cloudpivot.web.api.dao.UserMapper;
import com.authine.cloudpivot.web.api.dao.XmlvllMapper;
import com.authine.cloudpivot.web.api.domain.Constants;
import com.authine.cloudpivot.web.api.dubbo.DubboConfigService;
import com.authine.cloudpivot.web.api.service.ExecuteService;
import com.authine.cloudpivot.web.api.service.RecruitmentService;
import com.authine.cloudpivot.web.api.service.TimingTaskService;
import com.authine.cloudpivot.web.api.vo.AreaList;
import com.authine.cloudpivot.web.api.vo.ProjectDetail;
import com.authine.cloudpivot.web.api.vo.ResourcesDistribution;
import com.authine.cloudpivot.web.api.vo.TaskOnce;
import com.authine.cloudpivot.web.api.vo.TimingTask;
import com.authine.cloudpivot.web.api.vo.ZXQY;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.joda.time.DateTimeConstants;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import tk.mybatis.mapper.entity.Example;

import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.*;
import java.time.temporal.TemporalAdjusters;
import java.util.*;

import static com.authine.cloudpivot.web.api.util.AuthUtils.getUserId;

@Slf4j
@Service
public class TimingTaskServiceImpl implements TimingTaskService {

    @Reference(version = "1.00")
    private TaskReportFacade taskReportFacade;

    @Autowired
    private XmlvllMapper xmlvllMapper;

    @Autowired
    public DubboConfigService dubboConfigService;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private ProjectDetailMapper projectDetailMapper;

    @Autowired
    private TaskOnceMapper taskOnceMapper;

    @Autowired
    private ResourcesDistributionMapper  resourcesDistributionMapper;

    @Autowired
    private ResourcesDistributionServiceImpl  resourcesDistributionServiceImpl;

    @Autowired
    private RecruitmentService recruitmentService;

    @Autowired
    private ExecuteService executeService;

    @Override
    public void createRecruitmentReport() {
        //Date  now = new Date();
        Date now = getThisMonday();
        final Date realTime =  new Date();
        //根据id获取招聘需求提报的相关信息
        BizObjectQueryModel queryModel = new BizObjectQueryModel();
        PageableImpl pageable = new PageableImpl(0, 9999);
        queryModel.setSchemaCode("recruitmentDemand");
        queryModel.setQueryCode("recruitmentDemand");
        queryModel.setPageable(pageable);
        FilterExpression stateFilter = Q.it("sequenceStatus", FilterExpression.Op.Eq, "COMPLETED");
        FilterExpression endTimeFilter = Q.it("demandEndTime", FilterExpression.Op.Gte, now);
        //按确定人数
        FilterExpression.And and2 = Q.and(Lists.newArrayList(Q.it("recruitmentType", FilterExpression.Op.Eq, "按确定人数"),
                Q.it("stateModifiedTime", FilterExpression.Op.Gte,now),
                Q.it("stateModifiedTime", FilterExpression.Op.Lte,realTime)));

        FilterExpression.Or or1 = Q.or(Lists.newArrayList(endTimeFilter, and2));

        FilterExpression.And and = Q.and(Lists.newArrayList(stateFilter, or1));

        //FilterExpression timeExpression = Q.and(Arrays.asList(endTimeFilter));

        queryModel.setFilterExpr(and);
        BizObjectQueryModel.Options option = new BizObjectQueryModel.Options();
        option.setQueryDisplayType(QueryDisplayType.APPEND);
        option.setCustomDisplayColumns(Arrays.asList("id","name","creater","createdDeptId","demandDetails","demandCreatedTime", "demandEndTime","recruitWay","postJD","operator",
                "demandDetails","projectName","recruitmentType","frontOperator","operator","projectNameStr","customCode","subjectPerson","state","stateModifiedTime"));
        queryModel.setOptions(option);
        Page<BizObjectModel> recruitmentDatas = dubboConfigService.getBizObjectFacade().queryBizObjects(queryModel);

        Date[] stateModifiedTimeRegion = {now,realTime};


        recruitmentDatas.getContent().forEach(
                item->{
                    Map<String, Object> demandData = item.getData();

                    String demandId = (String) demandData.get("id");
                    SelectionValue user = ((ArrayList<SelectionValue>) demandData.get("creater")).get(0);
                    String userId = user.getId();

                    //获取所有周报的所有日期以及周期
                    Date startTime = (Date) demandData.get("demandCreatedTime");
                    Date endTime = (Date) demandData.get("demandEndTime");
                    String recruitmentType = MapUtils.getString(demandData, "recruitmentType", "");
                    //按确定人数的 需求只要 处理状态是 执行中就继续生成周报, 不管 要求完成时间
                    if ("按确定人数".equals(recruitmentType) && endTime.before(now)){
                        endTime = realTime;
                    }

                    List<String> weeklyReportDays = RecruitmentServiceImpl.getWeeklyDayTime(startTime,endTime);
                    List<String> cycles = RecruitmentServiceImpl.getCycle(weeklyReportDays);
                    List<String> weeklyReportDayList = new ArrayList<>();
                    List<String> cycleList = new ArrayList<>();
                    LocalDate today = now.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
                    String thisMonday = today.with(TemporalAdjusters.previousOrSame( DayOfWeek.MONDAY)).toString();
                    String thisSunday = today.with(TemporalAdjusters.nextOrSame(DayOfWeek.SUNDAY )).toString();
                    for(int i=0; i<weeklyReportDays.size(); i++){
                        if(weeklyReportDays.get(i).compareTo(thisMonday) >=0  && weeklyReportDays.get(i).compareTo(thisSunday) <=0){
                            weeklyReportDayList.add(weeklyReportDays.get(i));
                            cycleList.add(cycles.get(i));
                        }
                    }
                    String projectName  = (String) ((HashMap<String,Object>)demandData.get("projectName")).get("id");
                    List<Map<String, Object>> persons = recruitmentService.getMembers(projectName);
                    demandData.put("persons",persons);
                    recruitmentService.createWeekReport(demandId, userId, weeklyReportDayList, cycleList, demandData,"recruitmentDemand",stateModifiedTimeRegion);
                }
        );
    }

    @Override
    public void createExecuteReport() {
        Date now = getThisMonday();
        //根据id获取招聘需求提报的相关信息
        BizObjectQueryModel queryModel = new BizObjectQueryModel();
        PageableImpl pageable = new PageableImpl(0, 9999);
        queryModel.setSchemaCode("ZXXQTB");
        queryModel.setQueryCode("ZXXQTB");
        queryModel.setPageable(pageable);
        FilterExpression stateFilter = Q.it("state", FilterExpression.Op.Eq, "执行中");
        FilterExpression endTimeFilter = Q.it("activityEndTime", FilterExpression.Op.Gte, now);
        //FilterExpression timeExpression = Q.and(Arrays.asList(endTimeFilter));
        queryModel.setFilterExpr(stateFilter);
        queryModel.setFilterExpr(endTimeFilter);
        BizObjectQueryModel.Options option = new BizObjectQueryModel.Options();
        option.setQueryDisplayType(QueryDisplayType.APPEND);
        option.setCustomDisplayColumns(Arrays.asList("id","creater","createdDeptId","demandCreatedTime", "activityStartTime","activityEndTime",
                "operator","postJD","executeDetails","projectName","recruitmentType","frontOperator","operator","activityName", "projectNameStr",
                "industry","qthysm","projectNameStr","jobNature","subjectPerson"));
        queryModel.setOptions(option);
        Page<BizObjectModel> executeDatas = dubboConfigService.getBizObjectFacade().queryBizObjects(queryModel);

        //生成周报
        executeDatas.getContent().forEach(item->{
            Map<String, Object> executeData = item.getData();
            String demandId = (String) executeData.get("id");
            SelectionValue user = ((ArrayList<SelectionValue>) executeData.get("creater")).get(0);
            String userId = user.getId();
            //获取周报时间
            Map<String, Object> map = new HashMap<>();
            Date activityEndTime = (Date) executeData.get("activityEndTime");
            Date activityStartTime = (Date) executeData.get("activityStartTime");
            map.put("demandCreatedTime", activityStartTime);
            map.put("demandEndTime",activityEndTime);
            List<String> weeklyReportDays = RecruitmentServiceImpl.getWeeklyDayTime(map);
            List<String> cycles = RecruitmentServiceImpl.getCycle(weeklyReportDays);
            List<String> weeklyReportDayList = new ArrayList<>();
            List<String> cycleList = new ArrayList<>();
            //LocalDate today = LocalDate.of(2022,1,31);
            LocalDate today = now.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
            String thisMonday = today.with(TemporalAdjusters.previousOrSame( DayOfWeek.MONDAY)).toString();
            String thisSunday = today.with(TemporalAdjusters.nextOrSame(DayOfWeek.SUNDAY )).toString();
            for(int i=0; i<weeklyReportDays.size(); i++){
                if(weeklyReportDays.get(i).compareTo(thisMonday) >=0  && weeklyReportDays.get(i).compareTo(thisSunday) <=0){
                    weeklyReportDayList.add(weeklyReportDays.get(i));
                    cycleList.add(cycles.get(i));
                }
            }

            String projectName  = (String) ((HashMap<String,Object>)executeData.get("projectName")).get("id");
            List<Map<String, Object>> persons = recruitmentService.getMembers(projectName);
            executeData.put("persons",persons);
            Map<String,String> reportCreateTimeMap = getReportCreateTime(weeklyReportDayList, cycleList);
            executeService.createReport(demandId, executeData,"ZXXQTB", reportCreateTimeMap);
        });
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public  void createTimingTask(){

        //获取当前时间
        Date today=new Date();
        SimpleDateFormat sf=new SimpleDateFormat("yyyy-MM-dd 00:00:00");
        String nowTime= sf.format(today);
        SimpleDateFormat sf1=new SimpleDateFormat("yyyy-MM-dd");
        String newTime= sf1.format(today);

        Calendar c = Calendar.getInstance();
        c.setTime(today);
        //判断当前日期是几号
        int day=c.get(Calendar.DAY_OF_MONTH);
        //判断当前日期是周几
        int weekday = c.get(Calendar.DAY_OF_WEEK)-1;
        //周日计算和中国区别
        if(weekday==0){
            weekday=7;
        }
        // 当前日期是本月第几周
        boolean flag=false;
        int weeks = c.get(Calendar.WEEK_OF_MONTH);
        if(weeks % 2 == 0){
            flag=true;
        }

        List<TimingTask> list =xmlvllMapper.getItems(nowTime);
        String userIds="";
        String persons;
        List<String> rds=new ArrayList<>();
        for(TimingTask timingTask:list){
            persons =timingTask.getPerson();
            //每周一次
            if(Constants.ONCE_WEEK.equals(timingTask.getTimeNodes())&&weekday==timingTask.getTimes()
            ){
                if(StringUtils.isEmpty(userIds)){
                    userIds += this.createReceivers(persons);
                }else{
                    userIds += ","+this.createReceivers(persons);
                }

            }else if(Constants.ONCE_MONTH.equals(timingTask.getTimeNodes())&&day==timingTask.getTimes()
                    ){//每月一次
                if(StringUtils.isEmpty(userIds)){
                    userIds += this.createReceivers(persons);
                }else{
                    userIds += ","+this.createReceivers(persons);
                }
            }else if(Constants.ONCE_TWO_WEEKS.equals(timingTask.getTimeNodes())&&weekday==timingTask.getTimes()&&flag){
                //每两周一次
                if(StringUtils.isEmpty(userIds)){
                    userIds += this.createReceivers(persons);
                }else{
                    userIds += ","+this.createReceivers(persons);
                }
            }
            //查找到所有符合条件的任务分发数据
            if(!rds.contains(timingTask.getParentId())){
                rds.add(timingTask.getParentId());
            }
        }
        //调用发起流程接口
        if(StringUtils.isNotEmpty(userIds)){
            boolean results = sendMessage(userIds);
            //查找对应的
            if(results){
                String userId;
                String personDetail;
                String userName;
                for(String rd:rds){
                    List<TimingTask>  personList=resourcesDistributionServiceImpl.selectUserByRds(rd);
                    ResourcesDistribution resourcesDistribution=resourcesDistributionMapper.selectByPrimaryKey(rd);
                    if(StringUtils.isEmpty(resourcesDistribution.getDistributeresult())){
                        userName =newTime;
                    }else{
                        userName =resourcesDistribution.getDistributeresult()+"。"+newTime;
                    }
                    for(TimingTask person:personList){
                        personDetail=person.getPerson();
                        userId=this.createReceivers(personDetail);
                        if(userIds.contains(userId)){
                            if(userName.equals(newTime)){
                                userName +=":"+this. getPersonNames(personDetail);
                            }else {
                                userName +=","+this. getPersonNames(personDetail);
                            }
                        }
                    }
                    resourcesDistributionServiceImpl.updateDistributeResult(rd,userName);
                }
           }
        }
    };

    private  Map<String,String> getReportCreateTime(List<String> weeklyReportDays, List<String> cycles) {
        Map<String,String> reportCreateTimeMap =  new HashMap<>();
        for(int i=0; i<weeklyReportDays.size(); i++){
            String[] dateStr = weeklyReportDays.get(i).split("-");
            String year = dateStr[0];
            String month = dateStr[1];
            String cycle = cycles.get(i);
            reportCreateTimeMap.put(year+month+cycle,weeklyReportDays.get(i));
        }
        return reportCreateTimeMap;
    }

    /**
     * @Description : 发送钉钉待办通知
     * @param ： receivers
     * @author : Liun
     * @date : 2020/4/6
     */
    public boolean sendMessage(String receivers){
        IMMessageFacade imMessageFacade =this.dubboConfigService.getImMessageFacade();
        MessageModel messageModel = new MessageModel();
        messageModel.setReceivers(receivers);
        log.info("钉钉待办测试----------------------》"+receivers);
        messageModel.setUrl("form/detail?schemaCode=XMLVLL&sheetCode=XMLVLL&return=" +
                "/application/FescoAdecco/application-list/XMLVLL?parentId=2c928fbb7154db6c017155083d58021d&code=" +
                "XMLVLL&openMode&pcUrl&queryCode=&iframeAction=add");
        messageModel.setChannel(IMMessageChannelType.DINGTALK);
        messageModel.setMessageType(IMMessageType.BUSINESS_REMIND);
        messageModel.setContent("任务提交待办");
        messageModel.setTitle("任务提交待办");
        boolean result = imMessageFacade.sendMessage(messageModel);
        log.info("----------------------钉钉待办测试----------------------");
        return result;
    }


    /**
     * @Description : 生成接收对象数据
     * @param ： timingTask
     * @author : Liun
     * @date : 2020/4/6
     */
    public  String createReceivers(String person){
        JSONArray persons = JSONArray.fromObject(person);
        String personDetail;
        String userId="";
        for(Object personObj:persons){
            JSONObject personO=JSONObject.fromObject(personObj);
            personDetail=personO.get("id").toString();
            if(StringUtils.isEmpty(userId)){
                userId +=userMapper.getUserId(personDetail).getUserId();
            }else{
                userId +=","+ userMapper.getUserId(personDetail).getUserId();
            }
        }
        return userId;
    }

    /**
     * @Description : 自动更新项目执行经理区域省份表
     * @param ：
     * @author : Liun
     * @date : 2020/4/23
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public  void updateProjectDetailAuto(){
        //查询出所有无执行经理和区域的表单（项目执行经理区域省份表）
        List<ProjectDetail> projectDetails= projectDetailMapper.selectProjectDetail();
        //查询出所有的省份与区域关联关系表(执行区域表)
        List<ZXQY>  areas=projectDetailMapper.selectAREA();
        if(projectDetails.size()>0){
          for(ProjectDetail projectDetail:projectDetails){
              if(StringUtils.isNotEmpty(projectDetail.getSubjectname())){
                  List<AreaList> AreaLists =projectDetailMapper.selectAreaList(projectDetail.getSubjectname());
                  for(AreaList areaList:AreaLists){
                      for(ZXQY area:areas){
                          if(area.getProvince().equals(projectDetail.getProvince())
                                  &&area.getArea().equals(areaList.getArea())){
                              projectDetail.setArea(area.getArea());
                              projectDetail.setEmanager(areaList.getPerson());
                              projectDetail.setTerms(areaList.getParentid());
                              projectDetailMapper.updateByPrimaryKey(projectDetail);
                             }
                          }
                      }
                  }
              }
            }
        }




        /**
         * @Description : 一次性任务分发提醒任务提交
         * @param ： 
         * @author : Liun
         * @date : 2020/4/24
         */
        @Override
        public void  remindTaskOnce(){
            //一次性任务分发的子表只存在一条数据
            SimpleDateFormat sf=new SimpleDateFormat("yyyy-MM-dd 00:00:00");
            String nowTime=sf.format(new Date());

            //查找任务分发表单中分发状态为：是，任务为：一次性的数据
            Example exampleRD=new Example(ResourcesDistribution.class);
            Example.Criteria criteriaRD= exampleRD.createCriteria();
            criteriaRD.andEqualTo("distribute","是");
            criteriaRD.andEqualTo("taketype","一次性");
            List<ResourcesDistribution> resourcesDistributions=resourcesDistributionMapper.selectByExample(exampleRD);
            List<String> rdIds=new ArrayList<>();
            if(resourcesDistributions.size()>0){
                for(ResourcesDistribution rd:resourcesDistributions){
                    rdIds.add(rd.getId());
                }
            }
            //根据任务分发数据，查找子表一次性分发列表
            if(rdIds.size()>0){
                List<TaskOnce>  taskOnces=taskOnceMapper.selectByParentIds(rdIds,nowTime);
                String userIDs="";
                String userNames="";
                for(TaskOnce taskOnce:taskOnces){
                    if(StringUtils.isEmpty(userIDs)){
                        userIDs   +=  this.createReceivers(taskOnce.getPersons());
                        userNames +=  this.getPersonNames(taskOnce.getPersons());
                    }else{
                        userIDs +=","+ this.createReceivers(taskOnce.getPersons());
                        userNames +=","+this.getPersonNames(taskOnce.getPersons());
                    }
                  }
                //调用发起流程接口
                boolean result = sendMessage(userIDs);
                if(result){
                    resourcesDistributionServiceImpl.updateDistributeResult(rdIds.get(0),userNames);
                }
            }
        }


    /**
    * @Description : 根据当前人员获取当前人员姓名
    * @param ： person
    * @author : Liun
    * @date : 2020/4/24
    */
    public  String getPersonNames(String person){
        JSONArray persons = JSONArray.fromObject(person);
        String personDetail;
        String userName="";
        for(Object personObj:persons){
            JSONObject personO=JSONObject.fromObject(personObj);
            personDetail=personO.get("id").toString();
            if(StringUtils.isEmpty(userName)){
                userName +=userMapper.getUserId(personDetail).getName();
            }else{
                userName +=","+ userMapper.getUserId(personDetail).getName();
            }
        }
        return userName;
    }

    public static Date getThisMonday(){
        //本周周一
        LocalDateTime nowMonday = LocalDateTime.of(LocalDate.now(), LocalTime.MIN).with(DayOfWeek.MONDAY);
        ZoneId zone = ZoneId.systemDefault();
        Instant instant = nowMonday.atZone(zone).toInstant();
        Date dateime = Date.from(instant);
        return Date.from(instant);

    }

};











